package com.xsystem.criteria;

import java.util.HashMap;
import java.util.Map;

import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Restrictions;

@SuppressWarnings({ "rawtypes", "unchecked" })
public class XsystemExpression {
	public enum ExpressionType {
		EQ, GE, GT, LE, LT
	}

	private static final Map<String, Class> SUPPORTED_CLASSES = new HashMap<String, Class>();

	static {
		SUPPORTED_CLASSES.put("String", String.class);
		SUPPORTED_CLASSES.put("Integer", Integer.class);
		SUPPORTED_CLASSES.put("Long", Long.class);
		SUPPORTED_CLASSES.put("Double", Double.class);
	}

	private ExpressionType expressionType;

	private String propertyName;

	private Object value;

	private Class valueClass;

	private XsystemExpression(ExpressionType expressionType,
			String propertyName, String valueClassString, String valueString) {
		this.expressionType = expressionType;
		this.propertyName = propertyName;
		this.getObjectFromString(valueClassString, valueString);
	}

	private void getObjectFromString(String valueClassString, String valueString) {
		this.valueClass = SUPPORTED_CLASSES.get(valueClassString);
		try {
			if (valueClass.isAssignableFrom(Integer.class)) {
				value = Integer.parseInt(valueString);
			} else if (valueClass.isAssignableFrom(Long.class)) {
				value = Long.parseLong(valueString);
			} else if (valueClass.isAssignableFrom(Double.class)) {
				value = Double.parseDouble(valueString);
			} else {
				value = valueString;
			}
		} catch (ClassCastException e) {
			// TODO: throw exception
		}
	}

	public static XsystemExpression eq(String propertyName,
			String valueClassString, String valueString) {
		return createExpression(ExpressionType.EQ, propertyName,
				valueClassString, valueString);
	}

	public static XsystemExpression ge(String propertyName,
			String valueClassString, String valueString) {
		return createExpression(ExpressionType.GE, propertyName,
				valueClassString, valueString);
	}

	public static XsystemExpression gt(String propertyName,
			String valueClassString, String valueString) {
		return createExpression(ExpressionType.GT, propertyName,
				valueClassString, valueString);
	}

	public static XsystemExpression le(String propertyName,
			String valueClassString, String valueString) {
		return createExpression(ExpressionType.LE, propertyName,
				valueClassString, valueString);
	}

	public static XsystemExpression lt(String propertyName,
			String valueClassString, String valueString) {
		return createExpression(ExpressionType.LT, propertyName,
				valueClassString, valueString);
	}

	private static XsystemExpression createExpression(
			ExpressionType expressionType, String propertyName,
			String valueClassString, String valueString) {
		return new XsystemExpression(expressionType, propertyName,
				valueClassString, valueString);
	}

	public Criterion toHibernateCriterion() {
		Criterion result = null;
		if (expressionType == ExpressionType.EQ) {
			result = Restrictions.eq(propertyName, value);
		} else if (expressionType == ExpressionType.GE) {
			result = Restrictions.ge(propertyName, value);
		} else if (expressionType == ExpressionType.GT) {
			result = Restrictions.gt(propertyName, value);
		} else if (expressionType == ExpressionType.LE) {
			result = Restrictions.le(propertyName, value);
		} else if (expressionType == ExpressionType.LT) {
			result = Restrictions.lt(propertyName, value);
		}
		return result;
	}
}
